#include <stdlib.h>
#include <string.h>
#include "app_buffer.h"
#include "../thirdparty/log.h"

/*读写缓冲区的切换函数*/
static void App_buffer_swap(buff_t *main_buff)
{
    log_info("Start Swap write/read buff\n");
    pthread_mutex_lock(&main_buff->swap_lock);
    main_buff->buff_read_index = 1 - main_buff->buff_read_index;
    main_buff->buff_write_index = 1 - main_buff->buff_write_index;
    pthread_mutex_unlock(&main_buff->swap_lock);
}
/**
 * @brief 初始化一个缓冲区
 *
 * @return buff_t*
 */
buff_t *App_buffer_Init(void)
{
    /*1.定义主缓冲区结构体并为其分配内存*/
    buff_t *main_buff = (buff_t *)malloc(sizeof(buff_t) * 1);
    if (main_buff == NULL)
    {
        log_error("Memory malloc fail\n");
        return NULL;
    }
    /*2.初始化主缓冲中的子缓冲指针数组并为其分配内存*/
    main_buff->buff_read_index = 0;  // 默认数组内0号子缓冲为读缓冲
    main_buff->buff_write_index = 1; // 默认数组内1号自缓冲为写缓冲
    for (int i = 0; i < 2; i++)
    {
        main_buff->sub_buff_arr[i] = (sub_buff_t *)malloc(sizeof(sub_buff_t) * 1);
        main_buff->sub_buff_arr[i]->data_ptr = (char *)malloc(sizeof(char) * APP_BUFF_SIZE);
        main_buff->sub_buff_arr[i]->total_len = APP_BUFF_SIZE;
        main_buff->sub_buff_arr[i]->data_len = 0;
    }
    /*3.初始化线程锁*/
    pthread_mutex_init(&main_buff->read_lock, NULL);
    pthread_mutex_init(&main_buff->swap_lock, NULL);
    return main_buff;
}

/**
 * @brief 向缓冲区中写入数据
 *
 * @param data 待写入的数据
 * @param len 数据的长度
 * @return int 成功返回0 失败返回-1
 */
int App_buffer_Write(buff_t *main_buff, char *data, int len)
{
    /*1.检查数据的合法性[是否大于缓冲区的容量/大于一帧数据的最大长度]*/
    if (len > APP_BUFF_SIZE || len > 127)
    {
        log_error("data len illegality\n");
        return -1;
    }
    pthread_mutex_lock(&main_buff->swap_lock);
    /*2.取出写缓冲区*/
    sub_buff_t *write_buff = main_buff->sub_buff_arr[main_buff->buff_write_index];
    /*3.判断写缓冲区剩余容量是否足够*/
    int remain_capacity = write_buff->total_len - write_buff->data_len;
    if (len + 1 > remain_capacity)
    {
        log_error("not enough space , write fail\n");
        return -1;
    }
    /*4.向缓冲区中写入数据并更新数据长度*/
    write_buff->data_ptr[write_buff->data_len] = len;
    memcpy(write_buff->data_ptr + write_buff->data_len + 1, data, len);
    write_buff->data_len += (len + 1);
    pthread_mutex_unlock(&main_buff->swap_lock);
    return 0;
}

/**
 * @brief 从缓冲区中读取数据
 *
 * @param data_buff 装载读取到的数据的临时缓冲区
 * @param len 期望读取的长度
 * @return int 实际读取到数据的长度  失败返回-1
 */
int App_buffer_Read(buff_t *main_buff, char *data_buff, int len)
{
    pthread_mutex_lock(&main_buff->read_lock);
    /*1.取出读缓冲区*/
    sub_buff_t *read_buff = main_buff->sub_buff_arr[main_buff->buff_read_index];
    /*2.判断读缓冲区是否有数据*/
    if (read_buff->data_len == 0)
    {
        /*2.1若没有数据则进行读写缓冲区的切换*/
        App_buffer_swap(main_buff);
        /*2.2切换完成后再次取出读缓冲判断缓冲区内是否有数据*/
        read_buff = main_buff->sub_buff_arr[main_buff->buff_read_index];
        if (read_buff->data_len == 0)
        {
            /*2.3若仍旧没有没有数据返回0*/
            log_error("no data in read buffer\n");
            return 0;
        }
    }
    /*2.4若存在数据判断帧头数据长度是否小于容器长度*/
    if (len < read_buff->data_ptr[0])
    {
        log_error("data_buff no enough space\n");
        return -1;
    }
    /*3.将数据读取到临时缓冲区内*/
    int frame_data_len = read_buff->data_ptr[0];
    memcpy(data_buff,read_buff->data_ptr + 1,frame_data_len);
    /*4.读取完成后更新读缓冲区内的数据及数据长度*/
    read_buff->data_len -= (1 + frame_data_len);
    memmove(read_buff->data_ptr,read_buff->data_ptr + 1 + frame_data_len,read_buff->data_len);
    pthread_mutex_unlock(&main_buff->read_lock);
    /*5.返回实际读取到的数据长度*/
    return frame_data_len;
}

/**
 * @brief 销毁缓冲区
 *
 * @param buff 缓冲区的句柄
 */
void App_buffer_destroy(buff_t *buff)
{
    /*1.释放子缓冲区结构体内存*/
    for (int i = 0; i < 2; i++)
    {
        free(buff->sub_buff_arr[i]->data_ptr);
        free(buff->sub_buff_arr[i]);
    }
    /*2.销毁线程锁*/
    pthread_mutex_destroy(&buff->read_lock);
    pthread_mutex_destroy(&buff->swap_lock);
    /*3.释放主缓冲区结构体内存*/
    free(buff);
}
